import dbutil
from address_match import AddressMatch
from org_type_match import OrgTypeMatch
from AskAI import get_org_prop
from multi_thread_pool import MultiThreadPool

org_data_xxx = 'single_org_data'

"""
典型机构
于田县科克亚乡人民政府
且末县住房和城乡建设局
和布克赛尔县委网信办
中国共产主义青年团岳普湖县委员会
"""


class ProcessData_Area:
    def __init__(self):
        """初始化并加载地址匹配器"""
        self.addr_match = AddressMatch()
        self.addr_match.load_keywords()

    def update_areacode(self):
        """更新数据库中的地址信息"""
        # 1.查询机构列表
        org_list = dbutil.query_rows(f'select in_org_id, in_org_name, in_area_code  from {org_data_xxx}', ())

        update_list = []
        update_sql = f'update {org_data_xxx} set out_area=%s, out_area_name=%s where in_org_id =%s'

        # 2.处理每个机构的地址信息
        for org in org_list:
            in_area_code = self.get_in_area_code(org['in_area_code'])
            out_area = self.addr_match.get_best_match(in_area_code, org['in_org_name'])
            out_area_name = self.addr_match.get_address_name(out_area)
            update_list.append((out_area, out_area_name, org['in_org_id']))
            if (len(update_list) > 100):
                # 批量更新数据库记录，每批更新100条
                dbutil.batch_update(update_sql, update_list)
                update_list = []
                print("100 rows updated")
        if (len(update_list) > 0):
            dbutil.batch_update(update_sql, update_list)

    def get_in_area_code(self, in_area_code):
        """输入行政区域编码的非空判断
        :param in_area_code: 行政区域编码
        :return: 输入的行政区域编码
        """
        if in_area_code:
            return in_area_code[0:4]
        else:
            return ''


# 职能
class ProcessData_Duty:
    def __init__(self):
        """初始化并加载地址匹配器"""
        self.addr_match = AddressMatch()
        self.addr_match.load_keywords()
        self.orgtype_match = OrgTypeMatch()
        self.orgtype_match.load_keywords()

    def update_std_name(self):
        """更新数据库中的地址信息"""
        # 步骤1：查询机构列表
        org_list = dbutil.query_rows(f'select in_org_id, in_org_name, out_area  from {org_data_xxx}', ())

        update_list = []
        update_sql = f'update {org_data_xxx} set out_match_status=%s, out_nature=%s, out_duty=%s, out_std_name=%s where in_org_id =%s'

        # 步骤2：处理每个机构的地址信息
        for org in org_list:
            in_org_id = org['in_org_id']
            in_org_name = org['in_org_name']
            out_area = org['out_area']
            (nature, duty, l1_name, l2_name, l3_name, l4_name) = self.orgtype_match.get_best_match(in_org_name)

            # 匹配不到
            if nature is None:
                continue
            # 匹配到
            out_area_level = 1
            out_short_name = ''
            if len(out_area) == 2:
                out_area_level = 1
                out_short_name = l1_name
            elif len(out_area) == 4:
                out_area_level = 2
                out_short_name = l2_name
            elif len(out_area) == 6:
                out_area_level = 3
                out_short_name = l3_name
            elif len(out_area) >= 9:  # 乡镇，村
                out_area_level = 4
                out_short_name = l4_name

            out_area_name = self.addr_match.get_address_name(out_area, out_area_level)
            std_name = self.addr_match.format_std_name(out_area_name, out_short_name)

            # 更新数据库记录
            update_list.append(('rule', nature, duty, std_name, in_org_id))
            if (len(update_list) > 100):
                dbutil.batch_update(update_sql, update_list)
                update_list = []
                print("100 rows updated")
        if (len(update_list) > 0):
            dbutil.batch_update(update_sql, update_list)


def extract_worker(org):
    """线程任务"""
    in_org_id = org['in_org_id']
    in_org_name = org['in_org_name']
    out_area_name = org['out_area_name']
    out_match_status = org['out_match_status']
    # 调用大模型进行标准化
    prop = get_org_prop(in_org_name, out_area_name)
    nature = prop['nature']
    org_name = prop['org_name']
    print(f'提取{in_org_name} {out_area_name} -> {nature} {org_name}')
    if len(nature) > 0 and len(org_name) > 0:
        if out_match_status == 'todo':
            dbutil.update(
                f"update {org_data_xxx} set out_match_status ='ai', out_nature=%s, out_extract_name=%s where in_org_id =%s",
                (nature, org_name, in_org_id))
        else:
            dbutil.update(f"update {org_data_xxx} set  out_extract_name=%s where in_org_id =%s",
                          (org_name, in_org_id,))
    else:
        dbutil.update(f"update {org_data_xxx} set out_match_status ='err' where in_org_id =%s", (in_org_id,))
        pass


# 提取单位名称
class ProcessData_Extract:
    def __init__(self):
        pass

    def extract_name(self):
        org_list = dbutil.query_rows(
            f"""select in_org_id, in_org_name, out_area_name,out_match_status  from {org_data_xxx} where 
(out_std_name  like %s or out_match_status ='todo') and out_extract_name is null """, ('%{机构%'))
        thread_pool = MultiThreadPool(thread_num=1, msg_list=org_list, worker_function=extract_worker)
        thread_pool.start()
        thread_pool.wait_end()


# 生成正式名称
class ProcessData_FormatName:
    def __init__(self):
        self.addr_match = AddressMatch()
        self.addr_match.load_keywords()
        pass

    def get_ai_std_name(self, area_code, nature, short_name):
        # 获取区域层级
        area_level = self.addr_match.get_level_of_code(area_code)

        # 处理区域层级大于等于4（乡镇）的情况
        if area_level >= 4:
            # 处理"政府和两院"性质
            if nature == "政府和两院" or nature == '其他':
                area_name = self.addr_match.get_address_name(area_code, 4)
                return self.addr_match.format_std_name(area_name, '{乡镇政府}')
            # 处理"党委"性质
            elif nature == "党委":
                area_name = self.addr_match.get_address_name(area_code, 3)
                return f"{area_name}党委"

        # 默认情况处理
        area_name = self.addr_match.get_address_name(area_code, area_level)
        if area_name.endswith(short_name):
            return f"{area_name}"
        else:
            return f"{area_name}{short_name}"

    def extract_name(self):

        # 步骤1：查询机构列表
        org_list = dbutil.query_rows(
            f"""select in_org_id, in_org_name, out_area, out_std_name,out_nature, out_area_name,out_match_status,out_extract_name  from {org_data_xxx} where 
(out_std_name  like %s or out_match_status ='ai') and out_extract_name is not null """, ('%{机构%'))

        # 步骤2：处理每个机构
        for org in org_list:
            in_org_id = org['in_org_id']
            in_org_name = org['in_org_name']
            out_area = org['out_area']
            out_match_status = org['out_match_status']
            out_extract_name = org['out_extract_name']
            out_nature = org['out_nature']
            out_std_name = org['out_std_name']

            if out_match_status == 'ai':
                out_std_name = self.get_ai_std_name(out_area, out_nature, out_extract_name)
            else:
                out_std_name = out_std_name.replace('{机构名}', out_extract_name)

            dbutil.update(f"update {org_data_xxx} set  out_std_name=%s where in_org_id =%s",
                          (out_std_name, in_org_id,))


if __name__ == "__main__":
    print("初始化地址匹配器")
    updater = ProcessData_Area()
    print("完成地址匹配器加载，进行地址更新")
    updater.update_areacode()
    print("地址信息更新完成")
    print("进行基于规则的机构名称标准化")
    duty = ProcessData_Duty()
    duty.update_std_name()
    print("完成基于规则的机构名称标准化")
    print("进行基于AI对无法通过规则标准化的机构名称标准化")
    extract = ProcessData_Extract()
    extract.extract_name()
    format = ProcessData_FormatName()
    format.extract_name()
    print("完成基于AI对无法通过规则标准化的机构名称标准化")
